<?php

    use Doctrine\ORM\EntityManager;

    class WZ_Entity
    {
        /** @var Doctrine\ORM\EntityManager */
        static $em;
        static $_instance;
        
        public static function getInstance()
        {
            if (null === self::$_instance) {
                self::$_instance = new self();
            }
            return self::$_instance;
        }

        /**
         * Init Entity manager
         *
         * @return WZ_Entity
         */
        public function __construct()
        {
            $this->em = \WZ::get('em');
        }

        /**
         * Get entity repository
         *
         * @params mixed $entity
         * @return Doctrine\ORM\EntityRepository
         */
        public static function getRepository($entity)
        {
            return self::$_instance->em->getRepository(self::getClassName($entity));
        }

        /**
         * Flush entity manager
         *
         * @return void
         */
        public static function flushManager()
        {
            self::$_instance->em->flush();
        }

        /**
         * Get entity by parameter
         *
         * @param mixed $entity
         * @param string $key
         * @param bool $throw
         * @return object|null
         */
        public static function get($entity, $key = 'id', $throw = true)
        {
            $params = \WZ_Request::getInstance()->getParams();
            
            $value = (isset($params[$key])) ? $params[$key] : null;
            if (null === $value) {
                if (true === $throw) {
                    throw new InvalidArgumentException;
                }
                return null;
            }

            $match = self::$_instance->em->find(self::getClassName($entity), $value);
            if (!$match) {
                if (true === $throw) {
                    throw new InvalidArgumentException;
                }
                return null;
            }
            return $match;
        }

        /**
         * Find entity
         *
         * @param string $entity
         * @param mixed $key
         * @return object
         */
        public static function find($entity, $key)
        {
            return self::$_instance->em->find($entity, $key);
        }

        /**
         * Direct strategy
         *
         * @param mixed $entity
         * @param string $key
         * @param bool $throw
         * @return object|null
         */
        public static function direct($entity, $key, $throw = true)
        {
            return self::get($entity, $key, $throw);
        }

        /**
         * Get entity name
         *
         * @param mixed $entity
         * @return string
         */
        private static function getClassName($entity)
        {
            return is_object($entity) ? get_class($entity) : (string) $entity;
        }
    }
